package com.example.demo.config;

import com.example.demo.service.UserService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.JdbcUserDetailsManager;

import javax.sql.DataSource;
import java.io.PrintWriter;

/**
 * @ClassName SecurityConfig
 * @Description TODO
 * @Author leejiliang
 * @DateTime 2020/4/23 5:35 PM
 * @Version 1.0
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	/**
	 * 基于内存的方式添加内置用户名和密码信息
	 * @param http
	 * @throws Exception
	 */
//	@Override
//	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//		auth.inMemoryAuthentication()
//				.withUser("lee")
//				.password("lee")
//				.roles("admin")
//				.and()
//				.withUser("luo")
//				.password("luo")
//				.roles("user")
//		;
//	}

	/**
	 * 基于表单登陆的配置项
	 * @param http
	 * @throws Exception
	 */
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()
				.antMatchers("/admin/**").hasRole("admin")	//配置角色和url的匹配信息
				.antMatchers("/user/**").hasRole("user")	//同上
				.anyRequest() //保持在matchers后面
				.authenticated()
				.and()
				.formLogin()
				.loginPage("/login.html")	//指定登陆页面地址
				.loginProcessingUrl("/login")	//指定登陆post请求的
				.usernameParameter("user")		//表单中的username属性名称
				.passwordParameter("pass")		//登陆表单中密码属性名称
//				.defaultSuccessUrl("/success.html")		//登陆成功后跳转的URL，如果直接登陆的是登陆页面
//				.successForwardUrl("/success.html")		//登陆成功后跳转的URL，不论初次访问的页面是任何url
//				.failureUrl("/fail.html")		//登陆失败时跳转的URL
				.successHandler((req,resp,authentication)->{		//功能比较全，适用于处理处理前后端分离,支持返回json和页面跳转
					Object principal = authentication.getPrincipal();
					resp.setContentType("application/json;charset=utf-8");
					PrintWriter out = resp.getWriter();
					out.write(new ObjectMapper().writeValueAsString(principal));
					out.flush();
					out.close();
				})
				.permitAll()
//				.and()
//				.logout()
//				.logoutUrl("/logout.html")
//				.deleteCookies()
//				.clearAuthentication(true)
//				.invalidateHttpSession(true)
				.and()
				.csrf().disable();
	}

	/**
	 * 指定密码加密策略类
	 * @return
	 */
	@Bean
	PasswordEncoder passwordEncoder() {
		return NoOpPasswordEncoder.getInstance();
	}

	/**
	 * 定义角色高低信息
	 * @return
	 */
	@Bean
	RoleHierarchy roleHierarchy() {
		RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
		roleHierarchy.setHierarchy("ROLE_admin > ROLE_user");
		return roleHierarchy;
	}


	/**
	 * 通过jdbc的方式配置用户信息
	 */
//	@Autowired
//	DataSource dataSource;
//	@Override
//	@Bean
//	protected UserDetailsService userDetailsService() {
//		JdbcUserDetailsManager manager = new JdbcUserDetailsManager();
//		manager.setDataSource(dataSource);
//		if (!manager.userExists("lee")) {
//			manager.createUser(User.withUsername("lee").password("lee").roles("admin").build());
//		}
//		if (!manager.userExists("luo")) {
//			manager.createUser(User.withUsername("luo").password("luo").roles("user").build());
//		}
//		return manager;
//	}

	/**
	 * 完全diy的形式处理用户信息
	 */
	@Autowired
	private UserService userService;
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(userService);
	}
}
